package com.telit.common.filter;


import com.telit.common.response.ResultCode;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;


/**
 * Create by Chencf on 2022/07/11
 * 全局异常拦截Filter
 */
public class GlobalExceptionFilter implements Filter {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionFilter.class);

    // 定义 已知的异常与提示信息
    private static ImmutableMap<Class<? extends Throwable>, ResultCode> EXCEPTIONS;
    protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultCode> EXCEPTIONS_BUILDER = ImmutableMap.builder();

    // 定义 不打印日志的cod集合
    private static ImmutableSet<Integer> IGNORE_CODE;
    protected static ImmutableSet.Builder<Integer> IGNORE_CODE_BUILDER = ImmutableSet.builder();

    /**
     * Filter异常拦截
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        try {
            chain.doFilter(req, resp);
        } catch (Exception ex) {
            boolean flag = sendErrMsg(resp, ex);
            if (!flag) {
                Throwable cause = ex.getCause();
                if (cause != null) {
                    flag = sendErrMsg(resp, cause);
                }
            }

            if (!flag) {
                // 未知的错误异常，返回通用错误
                log.error("全局异常拦截-未知错误异常", ex);
            }
        }
    }

    /**
     * 根据异常类型，返回错误信息
     */
    private boolean sendErrMsg(ServletResponse resp, Throwable ex) {
        if (ex instanceof ResultCode) {
            ResultCode resultCode = (ResultCode) ex;
            if (!IGNORE_CODE.contains(resultCode.getCode()))
                log.warn("全局异常拦截:" + resultCode.getErrorMsg());
            return true;
        }

        ResultCode resultCode = EXCEPTIONS.get(ex.getClass());
        // 已预定义错误信息的系统异常，返回错误信息
        if (resultCode != null) {

            // 101开头的错误，向客户端返回异常消息时，携带Exception信息
            int code = resultCode.getCode();

            // sql相关异常，打印error日志 ,其他异常打印warning日志即可
            if (code / 100 == 203) {
//                if (EnterpriseWechatMessageUtil.isSqlErrorAlert() && LockUtil.lock("EnterpriseWechatMessage_SqlErrorAlert", 3600)) {
//                    EnterpriseWechatMessageUtil.sendMarkdownMsg("程序出现sql异常，请开发人员及时关注处理！", Collections.emptyList());
//                }
                log.error("全局异常拦截:" + resultCode.getErrorMsg(), ex);
            } else if (!IGNORE_CODE.contains(code)) {
                log.warn("全局异常拦截:" + resultCode.getErrorMsg());
            }

            if (code / 100 == 101) {
                // HttpResponseUtils.sendJsonMessage(resp, Result.build(resultCode, resultCode.getMsg() + ":" + ex.getMessage()));
                return true;
            }

            //HttpResponseUtils.sendJsonMessage(resp, Result.build(resultCode));
            return true;
        }
        return false;
    }

    @Override
    public void init(FilterConfig arg0) {
    }

    @Override
    public void destroy() {
    }
}
